import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONStringer;

/***********************************************************************
 * AutonomousEnemy class
 * 
 * Implements a ship that can move and attack on its own
 * 
 * Signature: public static AutonomousEnemy create (String name, Coord position,
 * int energy); public void install (); public void destroy (); public Coord
 * position (); public String name (); public void report (String message);
 * public void changePosition (Coord target); public boolean isOrbitable ();
 * public void takeDamage (int damage); public abstract char display (); public
 * abstract String toString (); public int energy (); public void move (int dx,
 * int dy) {
 ***********************************************************************/

public class AutonomousEnemy extends Ship implements Observer<Integer> {
  
  private boolean destroyed;
  
  protected AutonomousEnemy(String n, Coord p, int e) {
    super(n, p, e);
    this.destroyed = false;
  }
  
  public static AutonomousEnemy create(String n, Coord p, int e) {
    AutonomousEnemy sh = new AutonomousEnemy(n, p, e);
    sh.install();
    return sh;
  }
  
  public void install() {
    super.install();
    SpaceGame.clock().registerObserver(this);
  }
  
  public void destroy() {
    super.destroy();
    this.destroyed = true;
  }
  
  public void notify(Integer time) {
    if (destroyed)
      return;
    if (Util.random(2) == 0)
      this.autonomousMove();
    else
      this.autonomousFire();
  }
  
  protected void autonomousMove() {
    Coord shift;
    do
      shift = Util.randomShift(3);
    while (!this.position().add(shift).within(Coord.create(0, 0),
        SpaceGame.map().size().move(-1, -1)));
    this.move(shift.xPos(), shift.yPos());
  }
  
  protected void autonomousFire() {
    this.fire(SpaceGame.me().position().xPos() - this.position().xPos(),
        SpaceGame.me().position().yPos() - this.position().yPos());
  }
  
  public char display() {
    return '^';
  }
  
  public String toString() {
    return "Player " + this.name() + " " + this.position().toString() + " @ "
        + this.energy();
  }
  
  public static AutonomousEnemy fromJSON(JSONObject json) {
    try {
      if(json.getString("className").equals("AutonomousEnemy")) {
        return new AutonomousEnemy(json.getString("name"),
                                   new Coord().fromJSON(json.getJSONObject("position")),
                                   json.getInt("energy"));
      } else {
        System.err.println("\"" + json.toString() + "\" does not represent a AutonomousEnemy.");
        throw new RuntimeException("Cannot parse JSON, it is not a AutonomousEnemy!");
      }
    } catch (JSONException e) {
      e.printStackTrace();
      throw new RuntimeException("Unrecoverable JSON error, see above stack trace");
    }
    
  }

  @Override
  public String toJSONString() {
    try {
      return new JSONStringer()
                        .object() 
                          .key("className")
                          .value("AutonomousEnemy")
                          .key("name")
                          .value(this.name())
                          .key("position")
                          .value(this.position())
                          .key("energy")
                          .value(this.energy())
                        .endObject().toString();
    } catch (JSONException e) {
      e.printStackTrace();
      throw new RuntimeException("Unrecoverable JSON error, see above stack trace.");
    }
  }
  
}
